﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BrightIdeasSoftware;
using ROrganizer.Client;
using ROrganizer.Client.Files;
using ROrganizer.UI.Controllers.Core;
using ROrganizer.UI.Models;

namespace ROrganizer.UI.Controllers
{
    internal class LibraryManagerFormController : IModelFilter
    {
        private readonly FastObservableCollection<Entry> entries;
        private ApplicationSettings settings;

        public LibraryManagerFormController()
        {
            this.entries = new FastObservableCollection<Entry>();
            this.settings = ApplicationSettings.GetInstance();

            this.Refresh();
        }

        public event EventHandler Changed;
        private void OnChanged()
        {
            if (this.Changed != null)
                this.Changed(this, EventArgs.Empty);
        }

        public bool HideLinkedFiles { get; set; }
        public bool IsChanged { get; private set; }

        public ObservableCollection<Entry> Entries
        {
            get { return this.entries; }
        }

        public void GroupBy(GroupMode? grouping)
        {
        }

        public void ManageFolders(IWin32Window owner)
        {
            if (ViewManager.ShowFolderManager(owner))
            {
                this.Refresh();
                this.IsChanged = true;
            }
        }

        public void ShowDetails(IWin32Window owner, Entry entry)
        {
            if (ViewManager.ShowFileDetails(owner, entry.Target))
            {
                var repository = new HashRepository();
                var hentry = repository.Get(entry.Target);

                entry.IsLinked = hentry != null && hentry.IsLinked();
                this.OnChanged();
                this.IsChanged = true;
            }
        }

        public bool CanCommitChanges()
        {
            return true;
        }

        public void CommitChanges(IWin32Window owner)
        {
            ViewManager.ShowCommit(owner);
            this.Refresh();
        }

        private void Refresh()
        {
            var folders = this.settings.GetFolders();
            var files = FileEnumerator.EnumerateFiles(folders).ToArray();
            var hrepository = new HashRepository();
            var hentries = hrepository.All();
            var mrepository = new MetaRepository();
            var mentries = mrepository.All();

            var formatter = from file in files
                            let meta = mentries.FirstOrDefault(x => x.File.Path == file)
                            select new Entry
                            {
                                Name = Path.GetFileNameWithoutExtension(file),
                                Type = Path.GetExtension(file).Trim('.').ToUpper(),
                                Path = Path.GetDirectoryName(file),
                                Size = FileEnumerator.GetFileSize(file),
                                Resolution = Resolution.From(meta),
                                Runtime = meta != null ? meta.Info.Runtime : 0,
                                IsLinked = hentries.Any(x => x.File == file && x.IsLinked()),
                                Target = file,
                            };

            this.entries.Clear();
            this.entries.AddRange(formatter);
        }

        public class Entry
        {
            public string Name { get; set; }
            public string Type { get; set; }
            public string Path { get; set; }
            public long Size { get; set; }
            public Resolution Resolution { get; set; }
            public int Runtime { get; set; }

            public bool IsLinked { get; set; }
            public string Target { get; set; }
        }

        public enum GroupMode
        {
            ByType,
            ByFolder,
            ByQuality,
            BySize,
        }

        bool IModelFilter.Filter(object modelObject)
        {
            if (!this.HideLinkedFiles)
                return true;

            var entry = modelObject as Entry;
            return !entry.IsLinked;
        }
    }
}
